package com.starry.gateway.filter;

import com.starry.core.common.constants.CommonConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.util.Arrays;
import java.util.List;

import static java.lang.Long.parseLong;

/**
 * @Description 响应日志过滤器
 * @Author xiaoke
 *
 */
@Slf4j
@Component
public class ResponseLogFilter implements GlobalFilter, Ordered {
    static String resInfo = """
            
            ============== Response start ===================
            ==> url: {}；method: {} ({}ms)；
            {}
            ============== Response end ===================
            """;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            // 记录：url、方法、耗时、状态、响应头
            ServerHttpRequest request = exchange.getRequest();
            List<String> beginTimes = request.getHeaders().get(CommonConstant.GATEWAY_BEGIN_TIME_STR);
            String costTime = "-";
            if (beginTimes != null) {
                long startTime = parseLong(beginTimes.get(0));
                costTime = String.valueOf(System.currentTimeMillis() - startTime);
            }
            URI uri = request.getURI();
            HttpMethod method = request.getMethod();
            ServerHttpResponse response = exchange.getResponse();

            StringBuilder headerStr = new StringBuilder();
            response.getHeaders().forEach((headerName, headerValue) -> {
                headerStr.append("==> headers: ").append(headerName).append(":")
                        .append(Arrays.toString(headerValue.toArray())).append("\n");
            });
            headerStr.delete(headerStr.lastIndexOf("\n"), headerStr.length());
            log.info(resInfo, uri, method, costTime, headerStr);
        }));
    }


    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}
